﻿/*
 * Created by SharpDevelop.
 * User: StrunevskyDV
 * Date: 23.01.2010
 * Time: 9:30
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using Db4objects.Db4o;
using EmailJabber.EmailJabber.Core.Entities;
using EmailJabber.Entities.Entities;

namespace EmailJabber.DAL
{
    /// <summary>
    /// Description of DAL.
    /// </summary>
    public sealed class DAL
    {
        private static DAL instance = new DAL();
        private const string DATABASE = "neodatis";
        private readonly object sync = new object();

        public static DAL Instance
        {
            get
            {
                return instance;
            }
        }

        private DAL()
        {
        }

        /// <summary></summary>
        /// <returns></returns>
        public void AddEntry(LogEntry logEntry)
        {
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    db.Store(logEntry);
                }
            }
        }


        /// <summary></summary>
        /// <returns></returns>
        public List<LogEntry> GetLast(int minutesLast)
        {
            List<LogEntry> result = new List<LogEntry>();
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    IList<LogEntry> pilots = db.Query(new Predicate<LogEntry>(x => (x.Time > DateTime.Now.AddMinutes(-minutesLast))));
                    result.AddRange(pilots);
                    result.Sort(new Comparison<LogEntry>(SortByDate));
                }
            }

            return result;
        }

        private int SortByDate(LogEntry x, LogEntry y)
        {
            int result;
            if (x.Time > y.Time)
            {
                result = -1;
            }
            else
            {
                result = 1;
            }
            return result;
        }

        /// <summary></summary>
        /// <returns></returns>
        public List<LogEntry> Search(string query)
        {
            List<LogEntry> result = new List<LogEntry>();
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    IList<LogEntry> pilots = db.Query(new Predicate<LogEntry>(x => (x.Extra.Contains(query)) || x.Time.ToString().Contains(query)));
                    result.AddRange(pilots);
                    result.Sort(new Comparison<LogEntry>(SortByDate));
                }
            }
            return result;
        }

        public EntityBase GetEntityById(Guid entityId)
        {
            EntityBase result = null;
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    var items = db.Query<EntityBase>(item => item.Id.Equals(entityId));
                    if (items.Count > 0)
                    {
                        result = items[0];
                    }
                }
            }
            return result;
        }

        public List<T> FindEntity<T>(Predicate<T> filter)
        {
            var result=new List<T>();
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    result.AddRange( db.Query(filter));
                }
            }
            return result;
        }

        public void StoreEntity(EntityBase entity)
        {
        	DeleteEntityById(entity.Id);
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    db.Store(entity);
                }
            }
        }

        public void DeleteEntity(EntityBase entity)
        {
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    db.Delete(entity);
                }
            }
        }

        public void DeleteEntityById(Guid entityId)
        {
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    EntityBase result = null;
                    var items = db.Query<EntityBase>(item => item.Id.Equals(entityId));
                    foreach(EntityBase entity in items)
                    {
                    	db.Delete(entity);
                    }                    
                }
            }
        }

        public List<LogEntry> GetAll()
        {
            List<LogEntry> result = new List<LogEntry>();
            lock (sync)
            {
                using (IObjectContainer db = Db4oEmbedded.OpenFile(DATABASE))
                {
                    IList<LogEntry> pilots = db.Query<LogEntry>(typeof(LogEntry));
                    result.AddRange(pilots);
                    if (result.Count > 100)
                    {
                        result = result.GetRange(result.Count - 100, 100);
                        result.Sort(new Comparison<LogEntry>(SortByDate));
                    }
                }
            }
            return result;
        }
    }
}